﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using ReadWriteCsv;

namespace StockAnomalyDetector
{
    class Hunter
    {
        private ProgressBar bar;

        string[] datePaths; // e.g. D:\Data\20161010
        public Hunter()
        {
            datePaths = GetDatePaths();
            bar = new ProgressBar();
        }

        public Hunter(ProgressBar pbar) : this()
        {
            this.bar = pbar;
        }

        private string[] GetDatePaths()
        {
            string[] dirs = Directory.GetDirectories(@"D:\股票数据");
            return dirs;
        }

        private string[] GetStockPaths(string datePath)
        {
            string[] dirs = Directory.GetFiles(datePath);
            string[] withoutIndex =
                (from dir in dirs
                where dir != "SZ399001" && dir != "SH999999"
                select dir).ToArray(); // 排除上证指数和深证成指
            return withoutIndex;
        }

        private ProgressReporter progressReporter;

        public void Activate()
        {
            //新建task数组管理线程
            Task[] task = new Task[4];

            progressReporter = new ProgressReporter();
            bar.Maximum = 16;

            int coreNumber = 4;

            if (coreNumber == 4)
            {
                //给线程赋值 调用函数Process 传参数start 和 end
                task[0] = Task.Factory.StartNew(delegate { Process(0, 4); });
                task[1] = Task.Factory.StartNew(delegate { Process(4, 8); });
                task[2] = Task.Factory.StartNew(delegate { Process(8, 12); });
                task[3] = Task.Factory.StartNew(delegate { Process(12, 16); });
            }
            else if (coreNumber == 2)
            {
                task[0] = Task.Factory.StartNew(delegate { Process(0, bar.Maximum / 2); });
                task[1] = Task.Factory.StartNew(delegate { Process(bar.Maximum / 2, bar.Maximum); });
            }
            
        }


        //传给线程的函数 
        private void Process(int start, int end)//start 开始日期文件夹
        {

            //每个线程必须独自拥有reader 和 row
            CsvFileReader reader;
            CsvRow row = new CsvRow();
            InLimitUpDown inLimitUpDown = new InLimitUpDown();

            for (int i = start; i < end; i++)
            {
                string[] stockPaths = GetStockPaths(datePaths[i]); // e.g. D:\Data\20161011\SH600000 每个date内stocks可能不一样
                for (int j = 0; j < stockPaths.Length; j++)
                {
                    using (reader = new CsvFileReader(stockPaths[j]))
                    {

                        FormerData data = inLimitUpDown.formerData.Count == 0 ? null : inLimitUpDown.formerData.First(); ;
                        bool doCompare = true;
                        if (inLimitUpDown.formerData.Count == 0)
                        {
                            doCompare = false;
                        }
                        if (inLimitUpDown.formerData.Count != 0)
                        {
                            var stockcode = Convert.ToString(Regex.Match(stockPaths[j], @"[A-Z]{2}\d{6}"));
                            int delta;
                            do
                            {
                                data = inLimitUpDown.formerData.First();
                                delta = data.code.CompareTo(stockcode);
                                if (delta < 0)
                                {
                                    inLimitUpDown.formerData.Dequeue();
                                }
                            } while (delta < 0 && inLimitUpDown.formerData.Count != 0); // 前一天记录了收盘价，今天该股票未出现，丢弃前一天的数据。该过程可连续。
                            if (delta > 0) // 没有前一天的收盘价
                            {
                                doCompare = false;
                            }
                            else if (delta == 0) // 有前一天的收盘价
                            {
                                inLimitUpDown.formerData.Dequeue();
                            }

                        }
                       LimitUpDown limitUpDown = new LimitUpDown(row, data, doCompare);

                        Pattern repetition = new Repetition(row);//新建Repetition类 对象 repetition
                        BuyBack buyBack = new BuyBack(row);
                        FoxTail foxTail = new FoxTail(row);
                        Relay relay = new Relay(row);
                        Scanner scanner = new Scanner(row);
                        SchrodingerCat cat = new SchrodingerCat(row);
                        

                        //抓异常的函数（如RepAnalyze(CsvRow row) )的 边从CSV里读取边处理的 函数部分要写在此while循环之内
                        while (reader.ReadRow(row))
                        {
                            repetition.Analyze();
                            buyBack.Analyze();
                            foxTail.Analyze();
                            relay.Analyze();
                            scanner.Analyze();
                            cat.Analyze();
                            limitUpDown.Analyze();
                        }

                        //已经读取完CSV文件之后的函数部分写在这里
                        repetition.End(stockPaths[j]);
                        buyBack.End(stockPaths[j]);
                        foxTail.End(stockPaths[j]);
                        relay.End(stockPaths[j]);
                        scanner.End(stockPaths[j]);
                       limitUpDown.End(stockPaths[j], inLimitUpDown.currentData, i > 0 ? datePaths[i-1] : "");
                        cat.End(stockPaths[j]);
                    }
                }

                inLimitUpDown.Reset();

                progressReporter.ReportProgress(() =>
                {
                    bar.Value++;
                    if (bar.Value == bar.Maximum) // 进度条满，写文件
                    {
                        UpdateExceptionRecord(Repetition.writer, Repetition.exceptionList);
                        UpdateExceptionRecord(BuyBack.writer, BuyBack.exceptionList);
                        UpdateExceptionRecord(FoxTail.writer, FoxTail.exceptionList);
                        UpdateExceptionRecord(Relay.writer, Relay.exceptionList);
                        UpdateExceptionRecord(Flea.writer, Flea.exceptionList);
                        UpdateExceptionRecord(Fly.writer, Fly.fly);
                        UpdateExceptionRecord(InLimitUpDown.writer, InLimitUpDown.exceptionList);
                        UpdateExceptionRecord(SchrodingerCat.writer, SchrodingerCat.exceptionList);
                        UpdateExceptionRecord(Autodetector.writer, Autodetector.exceptionList);
                    }
                });
            }
        }

        void UpdateExceptionRecord(CsvFileWriter currentWriter, List<string> records)
        {
            foreach (var record in records)
            {
                currentWriter.WriteLine(record);
            }
            currentWriter.Close();
        }

    }//END class Hunter

}//END namespace StockAnomalyDetector

